package cn.oveay.classdesign.dao.base.impl;

import cn.oveay.classdesign.dao.base.BaseDao;
import cn.oveay.classdesign.dao.base.BaseQueryModel;
import cn.oveay.classdesign.util.jdbc.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseDaoImpl implements BaseDao {
    @Override
    public <T> int insert(T data) throws Exception {
        // JDBC
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getInsertSql(data);
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是影响到的行数
        int rows = pst.executeUpdate();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        // 5 释放资源
        pst.close();
        JdbcUtils.releaseConnection(con);
        return rows;
    }

    @Override
    public <T> int update(T data) throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getUpdateSql(data);
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是影响到的行数
        int rows = pst.executeUpdate();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        // 5 释放资源
        pst.close();
        JdbcUtils.releaseConnection(con);
        return rows;
    }

    @Override
    public int delete(int id) throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getDeleteSql(id);
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是影响到的行数
        int rows = pst.executeUpdate();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        // 5 释放资源
        pst.close();
        JdbcUtils.releaseConnection(con);
        return rows;
    }

    @Override
    public List findAll() throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getFindAllSql();
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是结果集
        ResultSet rs = pst.executeQuery();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        List list = new ArrayList();
        // 对结果集进行循环，每循环一次读取一条记录
        while (rs.next()) {
            // 将记录转换成对象
            Object data = rsToObject(rs);
            // 添加到集合
            list.add(data);
        }
        // 5 释放资源
        rs.close();
        pst.close();
        JdbcUtils.releaseConnection(con);

        return list;
    }

    @Override
    public List findByCondition(BaseQueryModel queryModel) throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getFindByConditionSql(queryModel);
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是结果集
        ResultSet rs = pst.executeQuery();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        List list = new ArrayList();
        // 对结果集进行循环，每循环一次读取一条记录
        while (rs.next()) {
            // 将记录转换成对象
            Object data = rsToObject(rs);
            // 添加到集合
            list.add(data);
        }
        // 5 释放资源
        rs.close();
        pst.close();
        JdbcUtils.releaseConnection(con);

        return list;

    }

    @Override
    public <T> T findOne(int id) throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = getFindAllSql() + " where id=" + id;
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是结果集
        ResultSet rs = pst.executeQuery();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        T result = null;
        // 对结果集进行循环，每循环一次读取一条记录
        if (rs.next()) {
            // 将记录转换成对象
            result = rsToObject(rs);
        }
        // 5 释放资源
        rs.close();
        pst.close();
        JdbcUtils.releaseConnection(con);

        return result;
    }

    @Override
    public Long findMaxId() throws Exception {
        // 1 创建Connection对象
        Connection con = JdbcUtils.getConnection();
        // 2 编写SQL语句，创建PreparedStatement对象
        String sql = "SELECT LAST_INSERT_ID() AS maxid";
        PreparedStatement pst = con.prepareStatement(sql);
        // 3 执行命令:executeUpdate,executeQuery
        // 返回值就是结果集
        ResultSet rs = pst.executeQuery();
        // 4 处理执行的结果(ResultSet中的记录=>java对象)
        Long result = null;
        // 对结果集进行循环，每循环一次读取一条记录
        if (rs.next()) {
            result = rs.getLong("maxid");
        }
        // 5 释放资源
        pst.close();
        rs.close();
        JdbcUtils.releaseConnection(con);

        return result;
    }

    // 多态，将产生具体的SQL语句的功能留给具体的子类来实现
    // 原因：只有具体的数据访问的子类才对应具体的表
    public abstract <T> String getInsertSql(T data);

    public abstract <T> String getUpdateSql(T data);

    public abstract String getDeleteSql(int id);

    public abstract String getFindAllSql();

    public abstract String getFindByConditionSql(BaseQueryModel queryModel);

    // 将记录转换成一个java对象
    public abstract <T> T rsToObject(ResultSet rs) throws Exception;
}
